/** \file    convert.h
  * \brief   Converts between different image in-memory representations.
  * \date    2001 - 2003
  * \author  Fedor Chelnokov
  * \version $Header: /home/cscom1r4/cvsroot/cs/include/imglib/convert.h,v 1.1 2004/02/04 14:43:23 cscom1r4 Exp $
  */

#ifndef _convert_h_
#define _convert_h_

#include "imageclass.h"
#include <cassert>
#include "cinline.h"
#include "fRGB.h"

namespace img {

class bitmap;

void shareQdata( AImage &aimg, const QImage &qimg );
void shareQdata( byte_image &aimg, const QImage &qimg );
void shareQdata( bitmap &bmp, const QImage &qimg );

///sets Arr2D-image to share current image data, after that Arr2D-image should be cleared or removed first
template <class A, class B>
void share_data(YATL::Arr2D<A> &a, const image<B> &b);
//vice versa
void share_data( byte_image &img, const AImage &aimg );

///creates QImage for bmp visualization, QImage will share bmp's data and must live shorter
QImage bmpImage(bitmap &bmp);
//the same for other image types
QImage qimg(const byte_image &img);

template <class R1, class R2>
inline void copy(R1 & r1, const R2 & r2);

///converts not black pixels to set bits, black colors to unset bits
template <> void copy(bitmap & dest, const QImage & source);
template <> void copy(bitmap & dest, const byte_image & source);

template <> void copy(AImage & dest, const QImage & source);
template <> void copy(AImage & dest, const byte_image & source);
template <> void copy(QImage & dest, const byte_image & source);

///function copies float pixel color image into byte pixel color image, !range 0-255!.
//@{
template <> void copy(AImage & dest, const FImage & source);
template <> void copy(QImage & dest, const FImage & source);
//@}

///function copies byte pixel color image into float pixel color image.
//@{
template <> void copy(FImage & dest, const AImage & source);
template <> void copy(FImage & dest, const byte_image & source);
template <> void copy(FImage & dest, const QImage & source);
//@}

///returns copy of original image and guranties that it has 32-bit depth
QImage trueColor( const QImage &source );

//////////////////////////////////////////
// conjugation with ImageMagick library //
//////////////////////////////////////////

///allocates copy of source
Image * magick(const byte_image & source);
///back conversion
void copy_mimage(const Image * source, byte_image & dest);

//////////////////////////////////////////////////////////////
// color converters - use them with the help of img::modify //
//////////////////////////////////////////////////////////////

inline fRGB convert(const float_color &c)
	{ return fRGB(c.r, c.g, c.b, c.a); }

inline float_color flow(const byte_color & c) 
	{ return float_color(c); }

inline byte_color grey_color(unsigned char c)
	{ return byte_color(c, c, c); }

inline byte_color premul(const byte_color & c)
	{ return byte_color(
		c.b * c.a / 255,
		c.g * c.a / 255,
		c.r * c.a / 255,
		c.a); }

inline byte_color invert_alpha(const byte_color & c)
	{ return byte_color(c.b, c.g, c.r, 255 - c.a); }

inline byte_color premul_invert_alpha(const byte_color & c)
	{ return byte_color(
		c.b * c.a / 255,
		c.g * c.a / 255,
		c.r * c.a / 255,
		255 - c.a); }

/////////////////////////////
// template implementation //
/////////////////////////////

template <class A, class B>
void share_data(YATL::Arr2D<A> & a, const image<B> & b)
{
	//Arr2D can not change scan order or alignment,
	//so the the only exit is to modify source itself
	image<B> & bb = const_cast<image<B>&>(b);

	if (b.alignment() > 1) 
		bb.resize(b.width(), b.height(), 1);

	if (b.order() == img::bottom_up) {
		bb.flip_order();
		bb.flip();
	}

	assert(b.scansize() == b.width()*sizeof(B));
	a.ShareData(const_cast<A*>(reinterpret_cast<const A*>(b.data())), 
		b.width(), b.height());
}

} //namespace img

#endif //_convert_h_
